#region license
/*
 * Copyright (C) 2007 CchenSoft.com
 * 
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License 2.1 or later, as
 * published by the Free Software Foundation. See the included License.txt
 * or http://www.gnu.org/copyleft/lesser.html for details.
 * 
 * Author: Billy Zhang
 */
#endregion

using System;
using System.Collections.Generic;
using System.Text;
using IBatisNet.DataMapper;
using IBatisNet.DataMapper.Configuration;
using System.Data;
using System.Collections;
using System.Xml;
using System.IO;
using System.Web;
using CchenSoft.Portal.Spi.Service;
using CchenSoft.Portal.Spi.Plugin;

namespace CchenSoft.Portal.DataAccess.IBatisNet
{
    public class IBatisDataService : IDataService
    {
        private ISqlMapper mapper;
        private IServicePlugin plugin;
        private IList mappings;
        private static object lockObj = new object();
        private string connectionString;
        private string sqlMapFile;

        public IBatisDataService()
        {
            mappings = new ArrayList();
        }

        public void Initialize()
        {

        }

        public string SqlMapFile
        {
            get { return sqlMapFile; }
            set { sqlMapFile = value; }
        }

        public string ConnectionString
        {
            get { return connectionString; }
            set { connectionString = value; }
        }

        private void BuildMapper()
        {
            lock (lockObj)
            {
                string xml = "";
                using (StreamReader reader = new StreamReader(plugin.Folder + sqlMapFile))
                {
                    xml = reader.ReadToEnd();
                }

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < mappings.Count; i++)
                    sb.AppendFormat("<sqlMap resource=\"{0}\"/>", mappings[i]).AppendFormat(Environment.NewLine);

                xml = xml.Replace("#sqlMaps#", sb.ToString());
                xml = xml.Replace("#connectionString#", connectionString);

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xml);

                DomSqlMapBuilder builder = new DomSqlMapBuilder();
                mapper = builder.Configure(doc);
            }
        }

        public void SetPlugin(IPlugin plugin)
        {
            this.plugin = (IServicePlugin)plugin;
        }

        public void Configure(IList mappingList)
        {
            for (int i = 0; i < mappingList.Count; i++)
            {
                if (!mappings.Contains(mappingList[i]))
                    mappings.Add(mappingList[i]);
            }
        }

        public ISqlMapper SqlMapper
        {
            get 
            {
                if (mapper == null)
                    BuildMapper();
                return mapper; 
            }
        }

        public object Insert(string statementName, object parameterObject)
        {
            return SqlMapper.Insert(statementName, parameterObject);
        }

        public object QueryForObject(string statementName, object parameterObject)
        {
            return SqlMapper.QueryForObject(statementName, parameterObject);
        }

        public T QueryForObject<T>(string statementName, object parameterObject)
        {
            return SqlMapper.QueryForObject<T>(statementName, parameterObject);
        }

        public int Update(string statementName, object parameterObject)
        {
            return SqlMapper.Update(statementName, parameterObject);
        }

        public int Delete(string statementName, object parameterObject)
        {
            return SqlMapper.Delete(statementName, parameterObject);
        }

        public IList QueryForList(string statementName, object parameterObject)
        {
            return SqlMapper.QueryForList(statementName, parameterObject);
        }

        public IList<T> QueryForList<T>(string statementName, object parameterObject)
        {
            return SqlMapper.QueryForList<T>(statementName, parameterObject);
        }

        public IList QueryForList(string statementName, object parameterObject, int skipResults, int maxResults)
        {
            return SqlMapper.QueryForList(statementName, parameterObject, skipResults, maxResults);
        }

        public IList<T> QueryForList<T>(string statementName, object parameterObject, int skipResults, int maxResults)
        {
            return SqlMapper.QueryForList<T>(statementName, parameterObject, skipResults, maxResults);
        }

        public object BeginTransaction()
        {
            ISqlMapSession session = SqlMapper.BeginTransaction();
            return session;
        }

        public void Commit(object obj)
        {
            ISqlMapSession session = (ISqlMapSession)obj;
            session.CommitTransaction();
        }

        public void Rollback(object obj)
        {
            ISqlMapSession session = (ISqlMapSession)obj;
            session.RollBackTransaction();
        }

        public IDbDataParameter CreateParameter(string name, object value)
        {
            if (!SqlMapper.IsSessionStarted)
                SqlMapper.OpenConnection();

            IDbDataParameter parameter = SqlMapper.LocalSession.CreateDataParameter();
            parameter.ParameterName = name;
            parameter.Value = value;

            return parameter;
        }

        public DataSet QueryForDataSet(string statementName, object parameterObject)
        {
            if (!SqlMapper.IsSessionStarted)
                SqlMapper.OpenConnection();

            IDbCommand command = SqlMapper.LocalSession.CreateCommand(CommandType.Text);
            command.CommandText = statementName;
            if (parameterObject is IList<IDbDataParameter>)
            {
                IList<IDbDataParameter> parameters = (IList<IDbDataParameter>)parameterObject;
                foreach (IDbDataParameter param in parameters)
                {
                    command.Parameters.Add(param);
                }
            }

            IDbDataAdapter adapter = SqlMapper.LocalSession.CreateDataAdapter(command);
            DataSet ds = new DataSet();
            adapter.Fill(ds);
            return ds;
        }
    }
}
